# coding:utf-8
import commands
import glob

import os

import re
import time
from pexpect import run

from app.modules.apps.container import ContainerApp

# 封装基于Adempiere的erp和owms应用程序.
from app.modules.common import network
from app.modules.common.port import protected_port_group_pool
from config import BeetleConfig


class AdempiereApp(ContainerApp):
    def __init__(self, app_id, app_name, zone_home_path, zone_alias, port,
                 nas_app_package_path, db_name):
        container_home = zone_home_path + '/ad_' + app_name

        port = str(port)

        super(AdempiereApp, self).__init__(app_id=app_id, app_name=app_name,
                                           zone_home_path=zone_home_path,
                                           zone_alias=zone_alias, port=port,
                                           nas_app_package_path=nas_app_package_path,
                                           container_home=container_home)

        self._db_dns = BeetleConfig.AD_DB_DNS
        self._db_port = BeetleConfig.AD_DB_PORT

        self._log_nohup_out_file_path = BeetleConfig.APP_LOG_PATH + '/%s.log' % app_id
        self._app_id = app_id
        self._adempiere_home = self._container_home + '/Adempiere'

        self._ad_db_user = db_name
        self._ad_web_port = port
        self._ad_ssl_port = re.sub(r'(.*)(\d{2})', '\g<1>43', port)
        self._ad_ajp_port = re.sub(r'(.*)(\d{2})', '\g<1>09', port)
        self._ad_jnp_port = re.sub(r'(.*)(\d{2})', r'\g<1>99', port)

        self._ad_ws_port = re.sub(r'(.*)(\d{2})', '\g<1>83', port)
        self._debug_port = re.sub(r'(.*)(\d{2})', '\g<1>87', port)
        self._ad_naming_port = re.sub(r'(.*)(\d{2})', '\g<1>99', port)
        self._ad_rmi_port = re.sub(r'(.*)(\d{2})', '\g<1>98', port)
        self._ad_rmi_bind_port = re.sub(r'(.*)(\d{2})', '\g<1>44', port)
        self._ad_invoker_bind_port = re.sub(r'(.*)(\d{2})', '\g<1>45', port)
        self._ad_connector_bind_port = re.sub(r'(.*)(\d{2})', '\g<1>46', port)
        self._ad_ejb_bind_port = re.sub(r'(.*)(\d{2})', '\g<1>73', port)
        self._ad_dubbo_port = re.sub(r'(.*)(\d{2})', '\g<1>90', port)

        self._jdk_home = '/usr/java/jdk1.6.0_45'

        self._app_config_home_path = self._config_home_path + '/' + self._zone_name + '/ad/*'

        if nas_app_package_path is None:
            self._version = '-1'
        else:
            self._version = self.get_version_by_version_file()

        self._prebuild_path = '/mnt/build/beetle/%s/%s/%s' % (
            self._app_name, self._app_name, self._version)

        self._ports = [self._ad_web_port,
                       self._ad_ssl_port,
                       self._ad_ajp_port,
                       self._ad_jnp_port,
                       self._ad_ws_port,
                       self._ad_naming_port,
                       self._ad_rmi_port,
                       self._ad_rmi_bind_port,
                       self._ad_invoker_bind_port,
                       self._ad_connector_bind_port,
                       self._ad_ejb_bind_port,
                       self._ad_dubbo_port]

    def set_runtime_param(self, nas_app_package, version=None, sub_path=''):

        self.app_log(
            content=u'配置应用的运行时参数:nas_app_package=%s version=%s sub_path=%s' % (
                nas_app_package, version, sub_path))

        super(AdempiereApp, self).set_runtime_param(
            nas_app_package=nas_app_package, version=version,
            sub_path=sub_path)

        if version is None or version == '':
            self._version = self.get_version_by_version_file()

        self._prebuild_path = '/mnt/build/beetle/%s/%s/%s' % (
            self._app_name, self._app_name, self._version)

        self.app_log('_prebuild_path地址变更为:%s' % self._prebuild_path)

    def install_app(self):

        self.run(command='/bin/bash -c "export ADEMPIERE_HOME=;"')

        if os.path.exists(self._prebuild_path + '/Adempiere.zip'):
            self.app_log(
                'A pre-build version \'%s\' has been found, preparing restore...' % self._version)

            self._restore_from_prebuild_file()
        else:
            self.app_log(
                'None pre-build version, preparing building new ad version \'%s\'' % self._version)

            self._download_zip_file()
            self._create_ad_config_file()
            self._run_ad_install()
            self._save_to_prebuild_package()

        self._config_app()

    def stop(self):
        _cmd = '/bin/bash -c "ps -ef |grep -w \'%s\' |grep -v \'grep\' |awk \'{print $2}\'|xargs kill -9"' % self._container_home
        # _cmd = 'lsof -i:%s |grep -i LISTEN|awk \'{print $2}\'|xargs kill -9' % str(self._port)
        self.run(command=_cmd, timeout=10)
        self.app_log('%s has been stoped.' % self._app_id)
        time.sleep(2)

    def restart(self):

        self.stop()

        self.run('mkdir -p %s' % BeetleConfig.APP_LOG_PATH)

        _cmd = '/bin/bash -c "cd %s;nohup sh RUN_Server2.sh > %s 2>&1 &"' % (
            self._adempiere_home + '/utils', self._log_nohup_out_file_path)
        self.app_log('Run command:%s' % _cmd)

        print self.run(command=_cmd)

        # self.run(command=_cmd, cwd=self._adempiere_home + '/utils', raise_on_error=True)

        self.app_log('%s has been restarted.' % self._app_id)

    def validate(self):
        pass

    def check_port_free(self):
        port_list = (self._ad_web_port,)

    # download ad zip file from nas.
    def _download_zip_file(self):
        self.run(r'mkdir -p %s' % self._container_home)

        self.run(command=r'/bin/bash -c "\cp -f %s %s"' % (
            self._nas_app_package_path + '/Adempiere*.zip',
            self._container_home + '/Adempiere.zip'),
                 raise_on_error=True)

        self.run(command=r'/bin/bash -c "\cp -f %s %s"' % (
            self._nas_app_package_path + '/webservice.zip',
            self._container_home + '/webservice.zip'),
                 raise_on_error=True)

        self.run(r'unzip -qo %s -d %s ' % (
            self._container_home + '/Adempiere.zip', self._container_home),
                 raise_on_error=True)

        self.run(r'unzip -qo %s -d %s ' % (
            self._container_home + '/webservice.zip', self._adempiere_home),
                 raise_on_error=True)

        self.run(r'/bin/bash -c "rm -f %s/*.zip"' % self._container_home)

    # Create a evn file for ad installation.
    def _create_ad_config_file(self):
        _evn_file_path = self._adempiere_home + '/AdempiereEnv.properties'

        print _evn_file_path

        _config_file_content = \
            '\n' \
            + 'ADEMPIERE_FTP_SERVER=127.0.0.1' + '\n' \
            + 'ADEMPIERE_FTP_PREFIX=my' + '\n' \
            + 'ADEMPIERE_DATE_VERSION=2016-5-21' + '\n' \
            + 'ADEMPIERE_DB_PASSWORD=adempiere' + '\n' \
            + 'ADEMPIERE_JNP_PORT=%s' % self._ad_jnp_port + '\n' \
            + 'ADEMPIERE_DB_SYSTEM=adempiere' + '\n' \
 \
            + 'ADEMPIERE_MAIL_SERVER=' + '\n' \
            + 'ADEMPIERE_DB_NAME=orcldb' + '\n' \
            + 'ADEMPIERE_KEYSTORECODEALIAS=adempiere' + '\n' \
            + 'ADEMPIERE_WEBSTORES=/wstore' + '\n' \
            + 'ADEMPIERE_KEYSTOREPASS=myPassword' + '\n' \
            + 'ADEMPIERE_ADMIN_EMAIL=' + '\n' \
            + 'ADEMPIERE_HOME=%s' % self._adempiere_home + '\n' \
            + 'ADEMPIERE_MAIN_VERSION=1.72.10' + '\n' \
            + 'ADEMPIERE_FTP_PASSWORD=user@host.com' + '\n' \
            + 'ADEMPIERE_MAIL_USER=' + '\n' \
            + 'ADEMPIERE_DB_USER=%s' % self._ad_db_user + '\n' \
 \
            + 'ADEMPIERE_JAVA_OPTIONS=-Xms1g -Xmx1g -Xmn200m -XX\\:SurvivorRatio\\=4 ' \
              '-XX\\:PermSize\\=64m -XX\\:MaxPermSize\\=172m -XX\\:ParallelGCThreads\\=2 ' \
              '-XX\\:+UseConcMarkSweepGC -XX\\:+UseParNewGC -XX\\:+CMSParallelRemarkEnabled ' \
              '-XX\\:+UseCMSCompactAtFullCollection -XX\\:CMSFullGCsBeforeCompaction\\=0 ' \
              '-XX\\:CMSInitiatingOccupancyFraction\\=55 -XX\\:+CMSClassUnloadingEnabled ' \
              '-XX\\:LargePageSizeInBytes\\=128M ' \
              '-Xdebug -Xrunjdwp:transport=dt_socket,address=%s,server=y,suspend=n' % self._debug_port + '\n' \
 \
            + 'ADEMPIERE_APPS_TYPE=jboss' + '\n' \
            + 'ADEMPIERE_APPS_SERVER=127.0.0.1' + '\n' \
            + 'ADEMPIERE_DB_PORT=1521' + '\n' \
            + 'ADEMPIERE_FTP_USER=anonymous' + '\n' \
            + 'ADEMPIERE_KEYSTOREWEBALIAS=adempiere' + '\n' \
            + 'ADEMPIERE_DB_PATH=oracle' + '\n' \
            + 'ADEMPIERE_SSL_PORT=%s' % self._ad_ssl_port + '\n' \
 \
            + 'ADEMPIERE_WEB_ALIAS=127.0.0.1' + '\n' \
            + 'ADEMPIERE_MAIL_UPDATED=' + '\n' \
            + 'ADEMPIERE_WEB_PORT=%s' % self._ad_web_port + '\n' \
            + 'ADEMPIERE_DB_URL=jdbc\:oracle\:thin\:@//%s\:1521/orcldb' % self._db_dns + '\n' \
            + 'ADEMPIERE_APPS_DEPLOY=%s/jboss/server/adempiere/deploy' % self._adempiere_home + '\n' \
            + 'ADEMPIERE_DB_SERVER=%s' % self._db_dns + '\n' \
 \
            + 'ADEMPIERE_KEYSTORE=%s/keystore/myKeystore' % self._adempiere_home + '\n' \
            + 'ADEMPIERE_MAIL_PASSWORD=' + '\n' \
            + 'JAVA_HOME=%s' % self._jdk_home + '\n' \
            + 'ADEMPIERE_DB_TYPE=oracle' + '\n' \
            + 'ADEMPIERE_DB_VERSION=2011-09-01' + '\n' \
            + 'ADEMPIERE_JAVA_TYPE=sun' + '\n'

        with open(_evn_file_path, 'w') as _f:
            _f.write(_config_file_content)

    def _run_ad_install(self):
        self.run('/bin/bash -c "chmod 777 %s/*.sh"' % self._adempiere_home)
        self.run(command='sh RUN_silentsetup.sh', cwd=self._adempiere_home,
                 raise_on_error=True, timeout=7200)
        # os.system('cd %s/utils;sh RUN_silentsetup.sh' % self._adempiere_home)

    # config all ad`s xml file
    def _config_app(self):
        self._config_ad_conf()

        self._config_ad_ejb()

        self._config_ad_server()

        self._config_ad_my_env()

        self._config_ad_propertie()

    # Adempiere/jboss/server/adempiere/conf/jboss-service.xml
    def _config_ad_conf(self):
        _conf_jboss_service_xml = self._adempiere_home + '/jboss/server/adempiere/conf/jboss-service.xml'

        with open(_conf_jboss_service_xml, 'r') as _f:
            _conf_jboss_service_xml_content = _f.read()

            _conf_jboss_service_xml_content = re.sub(
                r'(<attribute\s*name="Port">)(.*83)(</attribute>)',
                r'\g<1>%s\g<3>' % self._ad_ws_port,
                _conf_jboss_service_xml_content)

            _conf_jboss_service_xml_content = re.sub(
                r'(<attribute\s*name="Port">)(.*99)(</attribute>)',
                r'\g<1>%s\g<3>' % self._ad_naming_port,
                _conf_jboss_service_xml_content)

            _conf_jboss_service_xml_content = re.sub(
                r'(<attribute\s*name="RmiPort">)(.*98)(</attribute>)',
                r'\g<1>%s\g<3>' % self._ad_rmi_port,
                _conf_jboss_service_xml_content)

            _conf_jboss_service_xml_content = re.sub(
                r'(<attribute\s*name="RMIObjectPort">)(.*44)(</attribute>)',
                r'\g<1>%s\g<3>' % self._ad_rmi_bind_port,
                _conf_jboss_service_xml_content)

            _conf_jboss_service_xml_content = re.sub(
                r'(<attribute\s*name="ServerBindPort">)(.*45)(</attribute>)',
                r'\g<1>%s\g<3>' % self._ad_invoker_bind_port,
                _conf_jboss_service_xml_content)

            _conf_jboss_service_xml_content = re.sub(
                r'(<attribute\s*name="serverBindPort">)(.*46)(</attribute>)',
                r'\g<1>%s\g<3>' % self._ad_connector_bind_port,
                _conf_jboss_service_xml_content)
        with open(_conf_jboss_service_xml, 'w') as _f:
            _f.write(_conf_jboss_service_xml_content)

    # Adempiere/jboss/server/adempiere/deploy/jboss-web.deployer
    def _config_ad_server(self):
        _web_server_xml = self._adempiere_home + '/jboss/server/adempiere/deploy/jboss-web.deployer/server.xml'

        print _web_server_xml

        with open(_web_server_xml, 'r') as _f:
            _web_server_xml_content = _f.read()

            _web_server_xml_content = re.sub(
                r'(.*<Connector\s*port=")(\d*)("\s*address=".*\n\s*maxThreads)',
                "\g<1>%s\g<3>" % self._port,
                _web_server_xml_content)

            _web_server_xml_content = re.sub(
                r'(.*<Connector\s*port=")(\d*)(".*SSLEnabled="true")',
                "\g<1>%s\g<3>" % self._ad_ssl_port,
                _web_server_xml_content)

            _web_server_xml_content = re.sub(r'(keystoreFile=")(.*)(")',
                                             "\g<1>%s\g<3>" % (
                                                 self._adempiere_home + '/keystore/myKeystore'),
                                             _web_server_xml_content)

            _web_server_xml_content = re.sub(
                r'(redirectPort=")(.*)("\sacceptCount.*)',
                "\g<1>%s\g<3>" % self._ad_ssl_port,
                _web_server_xml_content)

            _web_server_xml_content = re.sub(r'(redirectPort=")(.*)("\s/>)',
                                             "\g<1>%s\g<3>" % self._ad_ssl_port,
                                             _web_server_xml_content)

            _web_server_xml_content = re.sub(
                r'(.*port=")(.*)("\s*address.*protocol="AJP/1.3")',
                "\g<1>%s\g<3>" % self._ad_ajp_port,
                _web_server_xml_content)

            with open(_web_server_xml, 'w') as _f:
                _f.write(_web_server_xml_content)

                # Adempiere/jboss/server/adempiere/deploy/ejb3.deployer/META-INF/jboss-service.xml

    def _config_ad_ejb(self):
        _ejb_jboss_service_xml = self._adempiere_home + '/jboss/server/adempiere/deploy/ejb3.deployer/META-INF/jboss-service.xml'

        with open(_ejb_jboss_service_xml, 'r') as _f:
            _ejb_jboss_service_xml_content = _f.read()

            _ejb_jboss_service_xml_content = re.sub(r'(:)(\d*)(</attribute>)',
                                                    r'\g<1>%s\g<3>' % self._ad_ejb_bind_port,
                                                    _ejb_jboss_service_xml_content)
        with open(_ejb_jboss_service_xml, 'w') as _f:
            _f.write(_ejb_jboss_service_xml_content)

    def get_version_by_version_file(self):

        _path = self._nas_app_package_path

        if not os.path.exists(_path):
            _info = 'Ad 的安装包路径没有找到, 请确认该路径是否正确,或者nas盘是否正确挂载?: %s' % str(_path)
            raise BaseException(_info)

        if str(_path).startswith('/mnt/winitRelease/latest.'):
            fs = glob.glob(_path + '/*.version')
            if len(fs) == 0:
                _version = '-1'
            else:
                _version = os.path.basename(fs[0])

        else:
            if os.path.isdir(_path):
                _filepath = _path
            else:
                _filepath = os.path.dirname(_path)

            _version = os.path.basename(os.path.abspath(_filepath))

        self.app_log('Defalut version is: %s' % _version)
        return _version

    def _restore_from_prebuild_file(self):

        self.run(command=r'mkdir -p %s' % self._container_home,
                 raise_on_error=True)

        self.run(command='/bin/bash -c "cp -f %s/Adempiere.zip %s"' % (
            self._prebuild_path, self._container_home),
                 raise_on_error=True)

        self.run(command=r'unzip -qo %s ' % 'Adempiere.zip',
                 cwd=self._container_home, raise_on_error=True)

        self.run(r'/bin/bash -c "rm -f %s/*.zip"' % self._container_home)

    def _save_to_prebuild_package(self):

        self.run(command='mkdir -p %s' % self._prebuild_path)

        self.run(command=r'/bin/bash -c "zip -r Adempiere.zip ./Adempiere/*"',
                 cwd=self._container_home)

        self.run(command=r'mv Adempiere.zip %s' % self._prebuild_path,
                 cwd=self._container_home)

    def _config_ad_my_env(self):
        _my_env_file = self._adempiere_home + '/utils/myEnvironment.sh'

        with open(_my_env_file, 'r') as _f:
            _my_env_file_content = _f.read()

            _my_env_file_content = re.sub("(\\nADEMPIERE_DB_SERVER=)(.*)",
                                          "\\g<1>%s" % self._db_dns,
                                          _my_env_file_content)

            _my_env_file_content = re.sub("(\\ADEMPIERE_DB_PORT=)(.*)",
                                          "\\g<1>%s" % self._db_port,
                                          _my_env_file_content)

            _my_env_file_content = re.sub(r'(\nADEMPIERE_HOME=)(.*)',
                                          r'\g<1>%s' % self._adempiere_home,
                                          _my_env_file_content)

            _my_env_file_content = re.sub("(\nADEMPIERE_DB_USER=)(.*)",
                                          "\\g<1>%s" % self._ad_db_user,
                                          _my_env_file_content)

            _my_env_file_content = re.sub("(\nADEMPIERE_DB_PASSWORD=)(.*)",
                                          "\\g<1>adempiere",
                                          _my_env_file_content)

            _my_env_file_content = re.sub("(\nADEMPIERE_WEB_PORT=)(.*)",
                                          "\\g<1>%s" % self._ad_web_port,
                                          _my_env_file_content)

            _my_env_file_content = re.sub("(\nADEMPIERE_JNP_PORT=)(.*)",
                                          "\\g<1>%s" % self._ad_jnp_port,
                                          _my_env_file_content)

            _my_env_file_content = re.sub(
                "(ADEMPIERE_JAVA_OPTIONS=.*,address=).*(,server.*)",
                "\\g<1>%s\\g<2>" % self._debug_port,
                _my_env_file_content)

            _my_env_file_content = re.sub(
                "(\nADEMPIERE_DB_URL=jdbc:oracle:thin:@//).*:.*(/.*)",
                "\\g<1>%s:%s\\g<2>" % (self._db_dns, self._db_port),
                _my_env_file_content)

            _my_env_file_content = re.sub("(\nADEMPIERE_SSL_PORT=)(.*)",
                                          "\\g<1>%s" % self._ad_ssl_port,
                                          _my_env_file_content)

            _my_env_file_content = re.sub("(\nADEMPIERE_APPS_SERVER=)(.*)",
                                          "\\g<1>%s" % '0.0.0.0',
                                          _my_env_file_content)

            _my_env_file_content = re.sub("(\nADEMPIERE_KEYSTORE=)(.*)",
                                          "\\g<1>%s" % (
                                              self._adempiere_home + '/keystore/myKeystore'),
                                          _my_env_file_content)

        with open(_my_env_file, 'w') as _f:
            _f.write(_my_env_file_content)

    def _config_ad_propertie(self):
        _propertie_file_path = self._adempiere_home + '/Adempiere.properties'

        with open(_propertie_file_path, 'r') as _f:
            _propertie_file_path_content = _f.read()

            _propertie_file_path_content = re.sub(r"(,UID\\=)(.*)(,)",
                                                  r"\g<1>%s\g<3>" % self._ad_db_user,
                                                  _propertie_file_path_content)

            _propertie_file_path_content = re.sub(
                "(\\n.*\\\\=).*({).*(-.*DBhost\\\\=).*(,DBport\\\\=).*(,DBname.*)",
                "\\g<1>%s\\g<2>%s\\g<3>%s\\g<4>%s\\g<5>" % (
                    self._db_dns, self._db_dns, self._db_dns, self._db_port),
                _propertie_file_path_content)

        with open(_propertie_file_path, 'w') as _f:
            _f.write(_propertie_file_path_content)
